// Text of project HelpURL2.9 written on 11/25/96 at 8:33 AM
// Beginning of file protoAboutText

// Before Script for "_userproto000"
begin

constant kNewtsCapeSymbol	:= '|Newtscape:Newtscape|;
DefConst('kBuild20, platformVersion.platformFile <> '|MessagePad|);

DefConst('kFixupHREFtext, func(template) // used in instance's afterScript
begin
	// extract&remove HREF info, emphasize URLs with underline
	// this version assumes syntactically correct URLs (no extra/missing chars)
	// <A HREF="href">label</A>
	// e.g., <A HREF="http://">home page</A>
	// e.g., <A HREF="mailto:...">email addr</A>
	local ARRAY styles := [], hrefs := [];
	local text := template.text, href;
	local regfont := template.viewFont, urlfont;
	if isFrame(regfont)
	then begin
		urlfont := Clone(regfont);
		urlfont.face := BOR(urlfont.face, kFaceUnderline);
		end
	else urlfont := BOR(regfont,tsUnderLine);

	local spos, qpos, epos := 0;

	while spos := StrPos(text, "<A HREF", epos)
	do begin
		// non-empty regular text before <A...
		if spos > epos
		then begin
			AddArraySlot(styles, spos-epos);
			AddArraySlot(styles, regfont);
			end;

		// extract href string: "http:..."
		qpos := StrPos(text,"\"",spos)+1;
		epos := StrPos(text,"\"",qpos);
		href := SubStr(text,qpos,epos-qpos);

		// remove HTML before label: <A HREF="...">
		epos := StrPos(text, ">", epos);
		StrMunger(text,spos,epos+1-spos, nil,0,nil);

		// remove HTML after label: </A>
		epos := StrPos(text,"</A>",spos);
		StrMunger(text,epos,4, nil,0,nil);

		// highlight label
		AddArraySlot(styles, epos-spos);
		AddArraySlot(styles, urlfont);

		// save href (for viewClickScript)
		AddArraySlot(hrefs, [href, spos, epos]);
		end;

	// any regular text at end?
	if epos < StrLen(text)
	then begin
		AddArraySlot(styles,StrLen(text)-epos);
		AddArraySlot(styles, regfont);
		end;

if kDebugOn
then begin
	Print("about text:");	Print(text);
	Print("about hrefs:");	Print(hrefs);
	end;

	template.styles := styles;
	template.hrefs := hrefs;
	template.text := text;
	RemoveSlot(template,'viewFont);
end);

end

_userproto000 :=
    {viewBounds: {left: 1, top: 1, right: -1, bottom: -15},
     viewFlags: 513,
     viewFont:
       simpleFont10 // note: this will be replaced by styles. coord with linespacing
       ,
     viewFormat: 257,
     viewLineSpacing: 12,
     text: "",
     viewClickScript:
       func(unit)
       begin
       /*
       	this finds the HREF that's clicked on (precomputed in afterScript)
       	highlights it
       	dispatches via urlCop or Newt's Cape
       	unhighlights
       */
       
       	local hrefentry, href, options := {}, spos, epos, app;
       	local INT cpos := :MyPointToCharOffset(GetPoint(firstX,unit), GetPoint(firstY,unit));
       
       //Print(cpos);
       //if cpos >=0 then Print(text[cpos]);
       
       	if cpos >= 0
       	then foreach hrefentry in hrefs // e.g., [["http:...", 10,20],...]
       		do if (spos := hrefentry[1]) <= cpos and
       				cpos <= (epos := hrefentry[2])
       		then begin
       			:SetHilite(spos, epos, true);
       			href := hrefEntry[0];
       
       			// dispatch using urlCop if installed (and url type is registered)
       			if (app := GetRoot().urlCop:?PreferredApp(href, 'getURL, {}))
       				and app <> kNewtsCapeSymbol
       			then GetRoot().urlCop:getURL(href,options) // .(app): ?
       
       			else if GetRoot().(kNewtsCapeSymbol) // Newt's Cape installed?
       			then begin
       				if BeginsWith(href,"mailto:")
       				then begin
       					options.subject := title; // from app
       					options.name 	:= SubStr(text,spos,epos-spos);
       					options.body 	:= "I really like" && title;
       					end;
       				//else options.noStatus := not kDebugOn; // hidden for end users?
       				GetRoot().(kNewtsCapeSymbol):getURL(href,options);
       				end
       			else if kDebugOn
       			then Print(href);
       
       			break :SetHilite(cpos,cpos,true); // would be nice to get rid of the caret too
       			end;
       	TRUE; // handled click
       end,
     viewJustify: 240,
     MyPointToCharOffset:
       func(x,y) 
       if kBuild20 or HasVariable(self, 'PointToCharOffset)
       then :PointToCharOffset(x,y)
       
       else begin // 1.x definition
       	local gb := :GlobalBox();
       	x := x - gb.left;
       	y := y - gb.top;
       	//Print([x,y]);
       
       	local spos, epos := -1;
       	local INT i, linenum := y div viewLineSpacing;
       	if linenum < 0 then return -1;
       
       	// find the line
       	// assume all cr-delimited with no wrapping
       	for i:=0 to linenum
       	do if epos
       		then begin
       			spos := epos+1;
       			epos := StrPos(text,"\n",spos);
       			end
       		else return -1;
       
       	local newstr := {
       		viewFont: styles[1],
       		msg: Functions.StrTruncate}:msg(SubStr(text,spos,epos), x);
       
       	spos + StrLen(newstr)-1; // I on end
       	end,
     viewClass: 81
    };


constant |layout_protoAboutText| := _userproto000;
// End of file protoAboutText
// Beginning of file aboutURLLayout

// Before Script for "aboutURLLayout"
/*
this is an example aboutBox.

aboutText is based on protoAboutText.
you can include simple <A HREF...> expressions in text.
be sure to call kFixUpHREFText in afterScript

note: for 1.x use, text lines must be short
(each end in return, no wrapping)
*/

aboutURLLayout :=
    {viewBounds: {left: 4, top: 4, right: -4, bottom: -4},
     viewJustify: 240,
     _proto: @180
    };

aboutText :=
    {
     text:
       "<A HREF=\"mailto:weyer@netaxs.com\">Steve Weyer</A>\n17 Timber Knoll Dr.\nWashington Crossing, PA 18977-1052\ninternet: weyer@netaxs.com\nAOL: SteveWeyer\nCIS: 74603,2051\n<A HREF=\"http://www.netaxs.com/~weyer/newton/releases.html\">http://www.netaxs.com/~weyer/newton/releases.html</A>"
     ,
     _proto: _userproto000
    };
AddStepForm(aboutURLLayout, aboutText);

// After Script for "aboutText"
thisView := aboutText;
call kFixupHREFtext with (thisView)




constant |layout_aboutURLLayout| := aboutURLLayout;
// End of file aboutURLLayout
// Beginning of file myProtoInfoButton

// Before Script for "_userproto001"
DefConst('kFixupInfoItems, func(template)
begin
	local items := template.AppInfoItems := [];
	if HasSlot(template, 'DoInfoAbout)
	then AddArraySlot(items, "About");
	if HasSlot(template, 'DoInfoHelp)
	then AddArraySlot(items, "Help");
	if HasSlot(template, 'DoInfoPrefs)
	then AddArraySlot(items, "Prefs");

	local auxItems := template:?GenInfoAuxItems();
	if isArray(auxItems) and Length(auxItems) > 0
		and HasSlot(template,'DoInfoAux)
	then begin
		AddArraySlot(items, 'pickSeparator);
		template.AuxOffset := Length(items);
		ArrayMunger(
			items, Length(items), 0,
			auxItems, 0, nil);
		end;
end)

_userproto001 :=
    {icon: GetPictAsBits("info icon", nil),
     viewBounds: {left: 6, top: 0, right: 19, bottom: 12},
     viewFlags: 513,
     viewFormat: 67109457,
     viewJustify: 17446,
     viewClickScript:
       func(unit)
       if :TrackHilite(unit)
       then if kBuild20 or HasVariable(:Parent(),'PopupMenu)
       	then :PopupMenu(AppInfoItems, {left: 0, top: 0})
       	else begin
       		local l := :LocalBox();
       		DoPopUp(AppInfoItems, l.right+3, l.top, self);
       		end,
     pickActionScript:
       func(index)
       begin
       	// MUST do this
       	:Hilite(nil);
       
       	if auxOffset and index >= auxOffset
       	then :DoInfoAux(:GenInfoAuxItems(), index - auxOffset)
       	else Perform(self, '{
       		About:	DoInfoAbout,
       		Help:	DoInfoHelp,
       		Prefs:	DoInfoPrefs}.(Intern(AppInfoItems[index])), []);
       end,
     pickCancelledScript: func() :Hilite(nil),
     AppInfoItems:
       [] // set in afterScript
       ,
     auxOffset: nil,
     viewClass: 76
    };


constant |layout_myProtoInfoButton| := _userproto001;
// End of file myProtoInfoButton
// Beginning of file HelpURLMain

// Before Script for "aboutHelpURLMain"
/*
this example shows how to include aboutText with embedded URLs that can be tapped.

and also create a dynamic help book using Newt's Cape.

this will also work on 1.x with some limitations:
- it assumes that each 'about line' is short: ends with a return and does not wrap
(long lines ok in help books since Newt's Cape does the text measurement/bounds computation)

- web pages would be retrieved using WebMail rather than NIE
*/
constant kDragRadius := 4;

aboutHelpURLMain :=
    {viewBounds: {left: 0, top: 30, right: 215, bottom: 160},
     title: "HelpURL",
     helpISBN: "helpurl.htm",
     helpText:
       "<!-- helpurl.htm -->\n<HTML>\n<HEAD><TITLE>^0 Help</TITLE>\t\t\t<!-- see afterScript. app.title -->\n<META HTTP-EQUIV=\"ISBN\" CONTENT=\"^1\"> \t<!-- see afterScript. app.helpISBN -->\n<META HTTP-EQUIV=\"SHORTTITLE\" CONTENT=\"^0 Help\"> \t<!-- see afterScript. app.title -->\n<!-- some reasonable fonts for help books. otherwise, depends on current user settings -->\n<META HTTP-EQUIV=\"PREF.H1\"\n\tCONTENT=\"{font: {family: 'espy, face: 1, size: 10}, above: 'top}\">\n<META HTTP-EQUIV=\"PREF.P\"\n\tCONTENT=\"{font: {family: 'espy, face: 0, size: 10}}\">\n<META HTTP-EQUIV=\"PREF.LI\"\n\tCONTENT=\"{font: {family: 'espy, face: 0, size: 10}}\">\n<META HTTP-EQUIV=\"PREF.PRE\"\n\tCONTENT=\"{font: {family: 'geneva, face: 0, size: 9}}\">\n</HEAD>\n\n<BODY>\n<H1><A NAME=\"Describe\">Describe HelpURL</A></H1>\n<P>\nHelpURL shows how to\n<OL>\n<LI>add URLs to an about box\n<LI>create a dynamic help book from HTML\n</OL>\n\n<P>\nThis works best with\n<A HREF=\"http://www.netaxs.com/~weyer/newton/newtscape.html\">Newt's Cape</A>\ninstalled on NOS 2.0 (though it will also work on 1.x).\n\n\n\n<H1><A NAME=\"DevelopAbout\">Develop an About Box with URLs</A></H1>\n<OL>\n<LI>Use the protoAboutText object\n<LI>Modify text, viewFont, etc. as appropriate.\n<LI>Text slot can contain simple HREF expressions only (see example).\n(For 1.x compatibility, use short lines with no wrapping.)\n<LI>This is processed at compile-time\n</OL>\n\n\n<H1><A NAME=\"UseAbout\">Use the About Box</A></H1>\n<OL>\n<LI>Users should install <A HREF=\"http://www.pobox.com/~flashsheridan\">URLcop</A>\nand/or <A HREF=\"http://www.netaxs.com/~weyer/newton/newtscape.html\">Newt's Cape</A>\n<LI>User taps on a URL in your About box\n<LI>It dispatches according to protocol types registered with URLcop;\nor, if just Newt's Cape is installed:\n\t<UL>\n\t<LI>http: -- sends document (from NIE or WebMail) to current \"htmlApp\" or \"helperApp\"\n\t<LI>mailto: -- generates Outbox message based on last mail transport\n\t<LI>news: -- dispatches to Newt's Paper\n\t</UL>\n</OL>\n\n\n<H1><A NAME=\"DevelopHelp\">Develop a Help Book with URLs</A></H1>\n\n<OL>\n<LI>Create helpText (like this)\n<LI>Set helpISBN slot (see afterScript for automatic substitution)\n<LI>Copy DoInfoHelp method to your app's infoButton\n<LI>install <A HREF=\"http://www.netaxs.com/~weyer/newton/newtscape.html\">Newt's Cape</A>\n<LI>select Help in your application (possibly making modifications iteratively)\n<LI>optionally, Save the help book using Newt's Cape; upload and distribute with your application\n</OL>\n\n\n<H1><A NAME=\"UseHelp\">Use the Help Book</A></H1>\n\n<OL>\n<LI>User installs either\n\t<UL>\n\t<LI>your saved help book\n\t<LI><A HREF=\"http://www.netaxs.com/~weyer/newton/newtscape.html\">Newt's Cape</A>\n\t</UL>\n<LI>Selects your i:Help button\n<LI>Help book opens (or Newt's Cape processes HTML to create help book dynamically)\n<LI>URLs to regular books and to web pages should work (links within help books might not work).\n</OL>\n\n\n\n<H1><A NAME=\"Understand\">Understand the Code</A></H1>\n<P>\nPrerequisites: familiarity with both NewtonScript and HTML.\n\n<P>To customize appearance, modify the Tag Prefs in Newt's Cape,\nor you can add document-specific style preferences --\nsee the Newt's Cape documentation for further details.\n\n\n<H1><A NAME=\"Distribute\">Distribute HelpURL</A></H1>\n<P>\nHelpURL is freeware, and may be distributed freely as long as all of the\nfiles are included and unmodified.  You are free to make modifications for\nyour own use. I would appreciate your references to the Newt's Cape URL:\nhttp://www.netaxs.com/~weyer/newton/newtscape.html\n\n<P>\n&copy; Copyright 1996, S. Weyer. All Rights Reserved Worldwide.\n\n\n<H1><A NAME=\"ContactAuthor\">Contact Author</A></H1>\n\n<PRE><A HREF=\"mailto:weyer@netaxs.com\">Steve Weyer</A>\n17 Timber Knoll Drive\nWashington Crossing, PA 18977-1052\nInternet: weyer@netaxs.com\nAmerica Online: SteveWeyer\nCompuserve: 74603,2051\n<A HREF=\"mailto:grs124@psu.edu\">Greg Simon</A> -- Newt's Cape co-developer\n<A HREF=\"http://www.netaxs.com/~weyer/newton/releases.html\">http://www.netaxs.com/~weyer/newton/releases.html</A>\n\n<A HREF=\"http://www.teleport.com/~gaia\">Gaia Home page</A> -- info about intranet wireless handheld solutions\n(re-using Newt's Cape technology).\n</PRE>\n\n</BODY>\n</HTML>"
     ,
     ReorientToScreen:
       func() // ROM_DefRotateFunc
       begin
       	:SyncView();
       	:RedoChildren();
       end,
     viewFlags: 608,
     viewClickScript:
       func(unit)	// not needed for 2.0 (removed in afterScript)
       self=helpURL
       and ABS(GetPoint(firstY, unit) - :GlobalBox().top) <= kDragRadius
       and ABS(GetPoint(firstX, unit) - :GlobalBox().left - ((viewBounds.right - viewBounds.left) div 2)) <= kDragRadius
       and :Drag(unit,nil),
     viewSetupFormScript:
       func()	// not needed for 2.0 (removed in afterScript)
       begin
       	self.helpurl := self; // for drag test
       	inherited:?viewSetupFormScript();
       end,
     viewDrawScript:
       func()	// not needed for 2.0 (removed in afterScript)
       begin
       	constant y := -1;
       	local INT x := (viewBounds.right - viewBounds.left) div 2;
       	:DrawShape(
       	MakeOval(x-kDragRadius, y-kDragRadius, x+kDragRadius, y+kDragRadius),
       		{transferMode: modeCopy,
       		fillPattern: vfFillWhite,
       		penSize: 2,
       		});
       end,
     viewFormat: 83952897,
     _proto: @180
    };

_view000 :=
    {title: "HelpURL",
     viewBounds: {left: 0, top: 2, right: 112, bottom: 18},
     _proto: @229
    };
AddStepForm(aboutHelpURLMain, _view000);


aboutView := LinkedSubview(aboutURLLayout,
    {viewBounds: {left: 34, top: 26, right: 138, bottom: 34}});
AddStepForm(aboutHelpURLMain, aboutView);
StepDeclare(aboutHelpURLMain, aboutView, 'aboutView);

_view001 := {_proto: @220};
AddStepForm(aboutHelpURLMain, _view001);

_view002 :=
    {
     DoInfoAbout:
       func()
       AboutView:open(),
     DoInfoHelp:
       func()
       if isInstance(helpISBN,'string)
       then begin
       	local libook := GetRoot().copperfield:whereIsBook(helpISBN); // help book installed?
       
       	local libentry := // undocumented checking/workaround
       		if libook and isFrame(libook.bookSoup)  
       		then libook.bookSoup;
       		// NOS 2.0 bug: bad pkg ref after previous book removed
       			
       	if libentry
       	then begin
       		local ttim := GetRoot().TinyTim, viewer := ttim;
       		local helpbook := libentry.book; // even more undocumented
       		if kBuild20 or GetVariable(ttim,'openHelpBook)
       		then ttim:close() // 2.0
       		else viewer := BuildContext({_proto: ttim, bookRef: helpBook}); // 1.x
       
       		viewer:openManual(helpbook);
       		end
       
       	else GetRoot().(kNewtsCapeSymbol):?dispatchFile( // create it dynamically
       		"text/html",
       		helpISBN,
       		helpText,
       		{pageSize:	'help,   		// help book size
       		//noStatus:	not kDebugOn,	// Newt's Cape invisible for end users?
       		});
       end,
     _proto: _userproto001
    };
AddStepForm(_view001, _view002);

// After Script for "_view002"
thisView := _view002;
// note: this button will work on either 2.0 or 1.x
if kBuild20
then thisView._proto := protoInfoButton // discard myProtoInfoButton
else call kFixupInfoItems with (thisView)





// After Script for "aboutHelpURLMain"
thisView := aboutHelpURLMain;
begin
// this substitutes title and isbn into the HTML helpText

// could do this via ParamStr except it doesn't work on very large strings
StrReplace(thisView.helpText, "^0", thisView.title, nil);
StrReplace(thisView.helpText, "^1", thisView.helpISBN, nil);


if kBuild20
then begin	// not needed since functionality provided automatically
	RemoveSlot(thisView,'viewSetupFormScript);
	Removeslot(thisView,'viewClickScript);
	Removeslot(thisView,'viewDrawScript);
	thisView.viewFormat := Bor(thisView.viewFormat, 208); //vfFrameDragger);
	end
else thisView.viewFormat := Bor(thisView.viewFormat, vfFrameMatte);
end


constant |layout_HelpURLMain| := aboutHelpURLMain;
// End of file HelpURLMain



